import { Node, UITransform, v3, Vec2, Vec3 } from 'cc';
import { ViewUtil } from 'db://app-game/core/utils/ViewUtil';
import { ecs } from 'db://app-game/libs/ecs/ECS';
import { RandomMoveModelComp } from '../../base/bll/move/RandomMoveSystem';
import { smc } from '../../singleton/SingletonModuleComp';
import { Inventory } from '../inventory/Inventory';
import { WeaponTypeEnum } from '../inventory/Inventory.type';
import { Joysitick } from '../joysitick/Joysitick';
import { Skills } from '../skills/Skills';
import { RoleChangeWeaponComp } from './bll/RoleChangeWeapon';
import { RoleControlComp } from './bll/RoleControlSystem';
import { RoleModelMoveComp } from './bll/RoleMoveSystem';
import { RoleModelComp } from './model/RoleModelComp';
import { RoleModelEquipmentComp } from './model/RoleModelEquipmentComp';
import { RoleModelJobComp } from './model/RoleModelJobComp';
import { RoleModelSkillsComp } from './model/RoleModelSkillsComp';
import { RoleModelStateComp } from './model/RoleModelStateComp';
import {
  RoleAttributeEnum,
  RoleLowerBodyAnimatorParamsEnum,
  RoleUpperBodyAnimatorParamsEnum,
  RoleUpperBodyStateEnum,
} from './Role.type';
import { RoleViewComp } from './view/RoleViewComp';

/** 角色 */
@ecs.register('Role')
export class Role extends ecs.Entity {
  // 数据层
  RoleModel: RoleModelComp; // 模型数据
  RoleModelJob: RoleModelJobComp; // 职业属性
  RoleModelEquipment: RoleModelEquipmentComp; // 装备属性
  RoleModelSkills: RoleModelSkillsComp; // 技能组件
  RoleModelState: RoleModelStateComp; // 状态组件

  // 业务层
  RoleChangeWeapon: RoleChangeWeaponComp; // 武器变更事件
  RoleControl!: RoleControlComp; // 控制组件（移动、攻击等）
  RoleModelMove!: RoleModelMoveComp; // 移动组件（移动、跳跃等）

  // 视图层
  RoleView: RoleViewComp; // 显示对象

  // 子实体
  Inventory!: Inventory; // 背包
  Skills!: Skills; // 技能栏

  init() {
    // 1.初始化实体常住ECS组件，定义实体特性
    this.addComponents<ecs.Comp>(
      RoleModelComp,
      RoleModelJobComp,
      RoleModelEquipmentComp,
      RoleModelSkillsComp
    );

    // 2.更新当前角色动态属性
    this.RoleModel.chp = this.RoleModel.attributes.get(RoleAttributeEnum.Hp).value;
    this.RoleModel.cmp = this.RoleModel.attributes.get(RoleAttributeEnum.Mp).value;
  }

  /** 加载角色显示对象（cc.Component在创建后，添加到ECS框架中，使实体上任何一个ECS组件都可以通过 ECS API 获取到视图层对象 */
  load(parent: Node, pos: Vec3 = Vec3.ZERO) {
    // 1.获取预制件路径
    const prefabPath = this.RoleModelJob.prefabPath;

    // 2.加载预制件，创建显示对象
    let node = ViewUtil.createPrefabNode(prefabPath);
    let mv = node.addComponent(RoleViewComp);
    this.add(mv);

    // 3.设置显示对象位置
    node.parent = parent;
    node.setPosition(pos);
  }

  /** 添加角色控制摇杆 */
  addRoleControl({
    moveJoysitick,
    attackJoysitick,
  }: {
    moveJoysitick: Joysitick;
    attackJoysitick: Joysitick;
  }) {
    this.add(RoleControlComp);
    this.RoleControl.moveJoysitick = moveJoysitick;
    this.RoleControl.attackJoysitick = attackJoysitick;
  }

  /** 角色武器变更事件 */
  changeWeapon(weaponId: number) {
    let rcw = this.add(RoleChangeWeaponComp);
    rcw.weaponId = weaponId;
  }

  /** 角色闲置 */
  roleIdle() {
    this.RoleView.upperBodyAnimator.setTrigger(RoleUpperBodyAnimatorParamsEnum.Idle);
    this.RoleView.lowerBodyAnimator.setTrigger(RoleLowerBodyAnimatorParamsEnum.Idle);
    this.remove(RoleModelMoveComp);
  }

  /** 角色移动 */
  roleWalk(velocity: Vec3, angle?: Vec3) {
    this.RoleView.upperBodyAnimator.setTrigger(RoleUpperBodyAnimatorParamsEnum.Walk);
    this.RoleView.lowerBodyAnimator.setTrigger(RoleLowerBodyAnimatorParamsEnum.Walk);
    const rmm = this.get(RoleModelMoveComp) || this.add(RoleModelMoveComp);
    rmm.velocity = velocity;
    rmm.angle = angle;
  }

  /** 角色奔跑 */
  roleRun(velocity: Vec3, angle?: Vec3) {
    this.RoleView.upperBodyAnimator.setTrigger(RoleUpperBodyAnimatorParamsEnum.Run);
    this.RoleView.lowerBodyAnimator.setTrigger(RoleLowerBodyAnimatorParamsEnum.Run);
    const rmm = this.get(RoleModelMoveComp) || this.add(RoleModelMoveComp);
    rmm.velocity = velocity;
    rmm.angle = angle;
  }

  /**
   * 角色攻击
   * @param boolean 摇杆激活状态
   */
  roleAttack(boolean: boolean) {
    if (this.RoleModelEquipment.weapon.type === WeaponTypeEnum.Bow) {
      this.RoleView.upperBodyAnimator.setNumber(RoleUpperBodyAnimatorParamsEnum.Bullet, 10);
      this.RoleView.upperBodyAnimator.setBool(RoleUpperBodyAnimatorParamsEnum.BulletReady, boolean);
      this.RoleView.upperBodyAnimator.setBool(RoleUpperBodyAnimatorParamsEnum.BowAttack, boolean);
    } else {
      this.RoleView.upperBodyAnimator.setBool(RoleUpperBodyAnimatorParamsEnum.Attack, boolean);
    }
  }

  /** 角色技能释放 */
  roleSkillRelease(skill: { skillId: number; skillLevel: number }): boolean {
    // 1.获取当前状态
    const stateName = this.getCurrentAnimation();
    // 2.判断当前状态是否优先于白名单
    const stateWhiteList = [
      ...this.RoleModelState.moveAnimationList,
      ...this.RoleModelState.attackAnimationList,
    ];
    // 3.如果当前状态优先于白名单中，则释放技能
    if (stateWhiteList.includes(stateName)) {
      // this.RoleModelState.skillId = skill.skillId;
      this.RoleView.upperBodyAnimator.setTrigger(RoleUpperBodyAnimatorParamsEnum.SkillQuick);
      return true;
    }
    return false;
  }

  /** 处理角色碰撞问题 */
  resetVelocity(velocity: Vec3): Vec3 {
    const wPos = this.RoleView.node.getComponent(UITransform).convertToWorldSpaceAR(v3());
    return smc.level.LevelMap.resetVelocity(wPos, velocity);
  }

  /** 获取角色当前播放动画 */
  getCurrentAnimation(): RoleUpperBodyStateEnum {
    return this.RoleView.upperBodyAnimator.curStateName as RoleUpperBodyStateEnum;
  }

  /** 添加背包 */
  addInventory(inventory: Inventory) {
    this.Inventory = inventory;
    this.addChild(inventory);
  }

  /** 添加技能栏 */
  addSkills(skills: Skills) {
    this.Skills = skills;
    this.addChild(skills);
  }

  /** 添加随机移动 */
  addRandomMove() {
    const rmm = this.add(RandomMoveModelComp);

    rmm.node = this.RoleView.node;
    rmm.word = smc.level.LevelMap.mapNode;
    rmm.range = new Vec2(2000, 2000);
    rmm.speedOfMove = 500;
    rmm.offset = 20;
    rmm.onComplete = this.moveComplete.bind(this);
  }

  /** 移动完成 */
  moveComplete() {
    setTimeout(() => {
      const rmm = this.add(RandomMoveModelComp);
      rmm.node = this.RoleView.node;
      rmm.word = smc.level.LevelMap.mapNode;
      rmm.range = new Vec2(2000, 2000);
      rmm.speedOfMove = 500;
      rmm.offset = 20;
      rmm.onComplete = this.moveComplete.bind(this);
    }, 1000);
  }
}
